//*****************************************************************************
// This code file is part of the Example WebPart Exception Handling
// This file was written by Adam Buenz [WSS MVP] of ARB Security Solutions, LLC
// http://www.sharepointsecurity.com
//
// This is a generic exception handling class file that is
// is meant to allow both writing of events to both the a text
// file in the executing assembly directory as well as creating
// an event source if it doesn't exist to write errors to there
// as well.
//
// This file and its parts is free for re-distribution, for use in both free
// and commercial applications, however this header must remain intact for legal
// use. This class file is distributed in the hope that it will
// be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//*****************************************************************************
//**************************************
// Current Version: 1.0.0.0 (Production)
//**************************************

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Xml;

namespace arb.Generic.SharedLibrary.exceptionHandling
{
    internal class GenericExceptionHandler
    {
        private static int _keepLogForXDays;
        private static TextWriterTraceListener _listener;
        private const string _logFieldDateFormat = "yyyyMMdd_HHmmss";
        private static Stream _logFile;
        private static string _logPath;
        private const string _logFileName = "ExampleLogFile_";
        private static string _eventSourceName = "MyWebPart";
        private static TraceSwitch traceSwitch;

        internal static int KeepLogForXDays
        {
            get
            {
                return GenericExceptionHandler._keepLogForXDays;
            }
            set
            {
                GenericExceptionHandler._keepLogForXDays = value;
            }
        }

        internal static System.Diagnostics.TraceLevel TraceLevel
        {
            get
            {
                return GenericExceptionHandler.traceSwitch.Level;
            }
            set
            {
                GenericExceptionHandler.traceSwitch.Level = value;
            }
        }
        internal static string EventSourceName
        {
            get
            {
                return _eventSourceName;
            }
            set
            {
                _eventSourceName = value;
            }
        }

        internal static string LogPath
        {
            get
            {
                return _logPath;
            }
            set
            {
                _logPath = value;
            }
        }

        static GenericExceptionHandler()
        {
            GenericExceptionHandler.traceSwitch = new TraceSwitch("SharePointServer", "Tracing for Your WebPart");
            GenericExceptionHandler._keepLogForXDays = 5;
        }

        private static void closeLogFile()
        {
            Trace.Flush();
            GenericExceptionHandler._listener.Flush();
            GenericExceptionHandler._listener.Close();
            Trace.Listeners.Remove(GenericExceptionHandler._listener);
            GenericExceptionHandler._logFile.Close();
        }

        internal static void FlushLogFile()
        {
            GenericExceptionHandler.closeLogFile();
            GenericExceptionHandler.setupLogFile();
            GenericExceptionHandler.removeOldLogFiles();
        }

        private static void removeOldLogFiles()
        {
            try
            {
                DateTime curATime = DateTime.Now.AddDays((double)(GenericExceptionHandler._keepLogForXDays * -1));
                string[] fArray = Directory.GetFiles(LogPath, "LogFile_*.log");
                foreach (string lFile in fArray)
                {
                    try
                    {
                        int lLength = lFile.IndexOf("LogFile_") + "LogFile_".Length;
                        if (lLength > 0)
                        {
                            int calcLength = (lFile.Length - lLength) - 4;
                            string getLength = lFile.Substring(lLength, calcLength);
                            DateTime repTimeMod = DateTime.ParseExact(getLength, "yyyyMMdd_HHmmss", CultureInfo.InvariantCulture);
                            if (repTimeMod.CompareTo(curATime) < 0)
                            {
                                File.Delete(lFile);
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        GenericExceptionHandler.WriteLine(System.Diagnostics.TraceLevel.Error, "An error has occured in the removeOldLogFiles  method(" + lFile + ") : " + exception.ToString(), "GenericExceptionHandlerClass");
                    }
                }
            }
            catch (Exception exception)
            {
                GenericExceptionHandler.WriteLine(System.Diagnostics.TraceLevel.Error, "An error has occured in the removeOldLogFiles method: " + exception.ToString(), "GenericExceptionHandlerClass");
            }
        }

        private static void setupLogFile()
        {
            string nPath = LogPath + @"\LogFile_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".log";           
            GenericExceptionHandler._logFile = File.Create(nPath);
            GenericExceptionHandler._listener = new TextWriterTraceListener(GenericExceptionHandler._logFile);
            Trace.Listeners.Add(GenericExceptionHandler._listener);
        }

        internal static void StartLogging()
        {
            GenericExceptionHandler.setupLogFile();
            GenericExceptionHandler.removeOldLogFiles();
        }

        internal static void StopLogging()
        {
            GenericExceptionHandler.closeLogFile();
        }

        internal static void WriteEventLog(System.Diagnostics.TraceLevel TraceLevel, string Message)
        {
            EventLogEntryType callMEntry;
            switch (TraceLevel)
            {
                case System.Diagnostics.TraceLevel.Error:
                    callMEntry = EventLogEntryType.Error;
                    break;

                case System.Diagnostics.TraceLevel.Warning:
                    callMEntry = EventLogEntryType.Warning;
                    break;

                default:
                    callMEntry = EventLogEntryType.Information;
                    break;
            }
            if (!EventLog.SourceExists(EventSourceName))
            {
                EventLog.CreateEventSource(EventSourceName, "Application");
            }
            EventLog sharepointSignalLog = new EventLog();
            sharepointSignalLog.Source = EventSourceName;
            sharepointSignalLog.WriteEntry(Message, callMEntry);
        }

        internal static void WriteImportantInfoLine(string Message)
        {
            Trace.WriteLine(DateTime.Now.ToString() + " : " + Message);
            GenericExceptionHandler.WriteEventLog(System.Diagnostics.TraceLevel.Info, Message);
        }

        internal static void WriteImportantInfoLine(string Message, string Category)
        {
            Trace.WriteLine(DateTime.Now.ToString() + " : " + Message, Category);
            GenericExceptionHandler.WriteEventLog(System.Diagnostics.TraceLevel.Info, Category + ": " + Message);
        }

        internal static void WriteImportantVerboseLine(string Message)
        {
            Trace.WriteLine(DateTime.Now.ToString() + " : " + Message);
        }

        internal static void WriteImportantVerboseLine(string Message, string Category)
        {
            Trace.WriteLine(DateTime.Now.ToString() + " : " + Message, Category);
        }

        internal static void WriteLine(System.Diagnostics.TraceLevel TraceLevel, string Message)
        {
            GenericExceptionHandler.WriteLine(DateTime.Now, TraceLevel, Message);
        }

        internal static void WriteLine(DateTime time, System.Diagnostics.TraceLevel TraceLevel, string Message)
        {
            int nLevel = (int)TraceLevel;
            if ((nLevel <= 2) || (((System.Diagnostics.TraceLevel)nLevel) <= GenericExceptionHandler.traceSwitch.Level))
            {
                Trace.WriteLine(time.ToString() + " : " + Message);
            }
            if ((nLevel != 4) && (((System.Diagnostics.TraceLevel)nLevel) <= GenericExceptionHandler.traceSwitch.Level))
            {
                GenericExceptionHandler.WriteEventLog(TraceLevel, Message);
            }
        }

        internal static void WriteLine(System.Diagnostics.TraceLevel TraceLevel, string Message, string Category)
        {
            GenericExceptionHandler.WriteLine(DateTime.Now, TraceLevel, Message, Category);
        }

        internal static void WriteLine(DateTime time, System.Diagnostics.TraceLevel TraceLevel, string Message, string Category)
        {
            int nLevel = (int)TraceLevel;
            if ((nLevel <= 2) || (((System.Diagnostics.TraceLevel)nLevel) <= GenericExceptionHandler.traceSwitch.Level))
            {
                Trace.WriteLine(time.ToString() + " : " + Message, Category);
            }
            if ((nLevel != 4) && (((System.Diagnostics.TraceLevel)nLevel) <= GenericExceptionHandler.traceSwitch.Level))
            {
                GenericExceptionHandler.WriteEventLog(TraceLevel, Category + ": " + Message);
            }
        }
    }
}